---
title: Subgraph Error Inclusion
subtitle: Configure the router to propagate subgraph errors to clients
description: Configure the Apollo GraphOS Router or Apollo Router Core to propagate subgraph errors to clients for all subgraphs or on a per-subgraph basis.
redirectFrom:
  - /graphos/routing/observability/subgraph-error-inclusion
---

By default, a GraphOS Router or Apollo Router Core redacts the details of subgraph errors in responses to clients. The router instead returns a default error with the following message:

```
Subgraph errors redacted
```

This redaction prevents potential leaks of sensitive information to the client. Using the `include_subgraph_errors` plugin, you can configure the router to propagate subgraph errors to clients instead. You can do this for all subgraphs, or on a per-subgraph basis.

## Configuration

To configure subgraph error inclusion, add the `include_subgraph_errors` plugin to your [YAML config file](/router/configuration/overview/#yaml-config-file), like so:

```yaml title="router.yaml"
# Option 1: Simple boolean toggle (default is false)
include_subgraph_errors:
  all: true # Propagate errors (message + extensions) from all subgraphs
  subgraphs:
    products: false # Override: Do not propagate errors from the 'products' subgraph (redact fully)
```

Any configuration under the `subgraphs` key takes precedence over the `all` configuration for that specific subgraph. In the example above, subgraph errors are included from all subgraphs _except_ the `products` subgraph, which will have its errors fully redacted.

If `all` is a boolean (`true` or `false`), then any configuration under `subgraphs` must also be a boolean.

```yaml title="router.yaml"
# Option 2: Fine-grained control using objects
include_subgraph_errors:
  all: # Default configuration for all subgraphs
    redact_message: true # Redact error messages globally
    allow_extensions_keys: # Allow only specific extension keys globally
      - code
      - trace_id
  subgraphs:
    # Subgraph 'products': Override global settings
    products:
      redact_message: false # Keep original error messages for 'products'
      allow_extensions_keys: # Extend global allow list for 'products'
        - reason # Allows 'code', 'trace_id' (from global) and 'reason'
      exclude_global_keys: # Exclude 'trace_id' from the inherited global list
        - trace_id # Allows 'code' (global) and 'reason' (subgraph), but not 'trace_id'

    # Subgraph 'inventory': Override global allow list with a deny list
    inventory:
      deny_extensions_keys: # Deny specific keys for 'inventory' (overrides global allow list)
        - internal_debug_info
        # Allows 'code', 'trace_id' (from global) but denies 'internal_debug_info'

    # Subgraph 'reviews': Use only common options, inheriting global allow/deny behavior
    reviews:
      redact_message: false # Override only message redaction, inherits global allow list
      exclude_global_keys: # Inherits global allow list, but excludes 'code'
        - code # Allows 'trace_id' but not 'code'

    # Subgraph 'accounts': Fully redact errors, overriding global object config
    accounts: false
```

<Note>

Using a `deny_extensions_keys` approach carries security risks because it follows a blocklist pattern—any sensitive information not explicitly included in the deny list might be exposed to clients if not covered by other rules (like a global `allow_extensions_keys`).

</Note>

For better security, we recommend either fully redacting subgraph errors (by setting the subgraph to `false`) or using the `allow_extensions_keys` approach (either globally or per-subgraph) to explicitly specify which error extension fields can be exposed to clients.

### Configuration Schema

The top-level `include_subgraph_errors` key accepts an object with the following keys:

| Key         | Type                                     | Description                                                                                                | Default |
| :---------- | :--------------------------------------- | :--------------------------------------------------------------------------------------------------------- | :------ |
| `all`       | `boolean` \| [ErrorMode Object](#errormode-object) | Configuration applied to all subgraphs unless overridden.                                                  | `false` |
| `subgraphs` | `map<string, boolean \| ErrorMode Object>` | Per-subgraph overrides for the `all` configuration. The key is the subgraph name.                            | `{}`    |

#### ErrorMode Object

This object provides fine-grained control over error propagation.

| Key                     | Type      | Description                                                                                                                                                              | Required |
| :---------------------- | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------- |
| `redact_message`        | `boolean` | If `true`, replaces the original error message with `Subgraph errors redacted`. If `false`, keeps the original message.                                                    | Optional |
| `allow_extensions_keys` | `[string]`  | Propagates **only** the specified keys in the `extensions` object. Cannot be used with `deny_extensions_keys` in the same object. If omitted, inherits global behavior. | Optional |
| `deny_extensions_keys`  | `[string]`  | Redacts the specified keys from the `extensions` object. Cannot be used with `allow_extensions_keys` in the same object. If omitted, inherits global behavior.           | Optional |
| `exclude_global_keys`   | `[string]`  | When inheriting a global `allow_extensions_keys` or `deny_extensions_keys` list, these keys are removed from the inherited list before applying subgraph-specific rules. | Optional |

### Key Behaviors & Precedence

1.  **Subgraph Specificity**: Configuration under `subgraphs.<subgraph_name>` always overrides the `all` configuration for that specific subgraph.
2.  **Boolean Override**: If `subgraphs.<subgraph_name>` is set to `true` or `false`, it completely overrides any `all` object configuration.
    *   `true`: Include the error, keep the original message, include all extensions (except `service` if explicitly denied later, though unlikely with `true`).
    *   `false`: Redact the error message and remove all extensions.
3.  **Global Boolean Restriction**: If `all` is set to `true` or `false`, then all entries under `subgraphs` must also be `true` or `false`. Object configurations are not allowed for subgraphs in this case.
4.  **Allow vs. Deny**: Within a single configuration object (either `all` or a specific subgraph), `allow_extensions_keys` and `deny_extensions_keys` are mutually exclusive.
5.  **Inheritance & Overrides (Object Config)**:
    *   If a subgraph config is an object, it inherits the behavior (`allow` or `deny` list, `redact_message`) from the global `all` object config by default.
    *   `redact_message` in the subgraph object overrides the global `redact_message`.
    *   `allow_extensions_keys` in the subgraph object:
        *   Overrides a global `deny_extensions_keys` list.
        *   Extends a global `allow_extensions_keys` list (after applying `exclude_global_keys`).
    *   `deny_extensions_keys` in the subgraph object:
        *   Overrides a global `allow_extensions_keys` list.
        *   Extends a global `deny_extensions_keys` list (after applying `exclude_global_keys`).
    *   `exclude_global_keys` removes keys from the inherited global list *before* the subgraph's `allow` or `deny` list is applied or extended.
6.  **`service` Extension**: The `service` extension (containing the subgraph name) is added by default if errors are included for a subgraph, unless it's explicitly removed by an `allow_extensions_keys` list (that doesn't include `"service"`) or a `deny_extensions_keys` list (that includes `"service"`).

## Sending errors to GraphOS

Reporting subgraph errors to GraphOS is configured separately and is not affected by client-facing error inclusion settings. See the [GraphOS reporting docs](/router/configuration/telemetry/apollo-telemetry).

## Logging GraphQL request errors

To log the GraphQL error responses (i.e., messages returned in the GraphQL `errors` array) from the router, see the [logging configuration documentation](/router/configuration/telemetry/exporters/logging/overview).

## Exposing subgraph name via `service` extension

If errors are included for a particular subgraph (i.e., not fully redacted by setting its config to `false`), the router attempts to add the subgraph's name to the error's `extensions` object under the key `service`.

This `service` extension key is treated like any other extension key and is subject to the `allow_extensions_keys` and `deny_extensions_keys` rules.

*   If using `allow_extensions_keys`, you must include `"service"` in the list if you want it to be propagated.
*   If using `deny_extensions_keys`, including `"service"` will prevent it from being propagated.
*   If no allow/deny lists apply (e.g., `all: true`), `"service"` will be included by default.

**Example:**

Assume `include_subgraph_errors.all` is configured as:
```yaml
all:
  redact_message: false
  allow_extensions_keys:
    - code # Allows only 'code', implicitly denying 'service'
```
If the `products` subgraph returns an error like `{"message": "Invalid ID", "extensions": {"code": "BAD_USER_INPUT"}}`, the final error sent to the client will be:
```json
{
  "message": "Invalid ID",
  "path": [...],
  "extensions": {
    "code": "BAD_USER_INPUT"
    // "service": "products" is NOT included because it wasn't in allow_extensions_keys
  }
}
```

If the configuration was instead:
```yaml
all:
  redact_message: false
  allow_extensions_keys:
    - code
    - service # Explicitly allow 'service'
```
The final error would be:
```json
{
  "data": null,
  "errors": [
    {
      "message": "Invalid product ID",
      "path": [],
      "extensions": {
        "service": "products",
      }
    }
  ]
}
```
